package Game.scene;

import static org.lwjgl.opengl.GL11.GL_AMBIENT;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_DIFFUSE;
import static org.lwjgl.opengl.GL11.GL_LIGHT0;
import static org.lwjgl.opengl.GL11.GL_LIGHTING;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_POSITION;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glLight;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glRotatef;
import static org.lwjgl.opengl.GL11.glScalef;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.util.glu.GLU.gluLookAt;
import static org.lwjgl.util.glu.GLU.gluPerspective;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.LinkedList;

import org.lwjgl.input.Keyboard;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import Units.CannonBall;
import Units.EnemyTank;
import Units.Factory;
import Units.Tank;

import Game.Cube;
import Game.GameModel;
import Game.GameObject;
import Game.screen.TelaEntrada;
import Game.screen.TelaGameOver;
import Game.window.GameMain;

public class Stage extends IScene {

	private final static double FOVY = 45.0;
	private final static double NEAR = 0.1;
	private final static double FAR = 3000.0;
	private float angTY;
	
	public float score;

	private static LinkedList<GameObject> childList = new LinkedList<GameObject>();

	float worldX, worldY, worldZ;
	Tank hero;
	TelaEntrada cube;
	TelaGameOver gameOverScreen;

	@Override
	public void init() {
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_LIGHTING);

		int width = GameMain.instance.display_parent.getWidth();
		int height = GameMain.instance.display_parent.getHeight();

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		float aspect = (float) width / (float) height;
		gluPerspective((float) FOVY, (float) aspect, (float) NEAR, (float) FAR);
		glMatrixMode(GL_MODELVIEW);

		hero = (Tank) Factory.newTankPlayer();
		cube = new TelaEntrada(hero.x,hero.y,hero.z,"LogoUNIVALI.png");
		cube.w = 220.4f;
		cube.h = 164.f;
		cube.d = 2;
		cube.rotateX = 87;
		addChild(cube);
	}
	
	private void gameOver(){
		childList.clear();
		gameOverScreen = new TelaGameOver(hero.x,hero.y,hero.z, "gameOverScreen.png");
		gameOverScreen.w = 220.4f;
		gameOverScreen.h = 164.f;
		gameOverScreen.d = 2;
		gameOverScreen.rotateX = 87;
		addChild( gameOverScreen );
	}

	private long lastCreatedTank;
	private boolean gameStarted;
	private long keyboardCooldown;
	private boolean gameOver;
	private boolean gameplay;

	public static void addChild(GameObject gameObject) {
		childList.add(gameObject);
	}

	@Override
	public void update(long diftime) {
		
		if(!hero.alive){
			if(childList.contains(hero)){
				hero.x = 0; hero.y = 0; hero.z = 0;
				childList.remove(hero);
			}
			gameOver();
			gameOver = true;
			gameplay = false;
		}
		
		if (Keyboard.isKeyDown(Keyboard.KEY_RETURN)){
			
		}

		if (Keyboard.isKeyDown(Keyboard.KEY_RETURN)){
			if(!gameOver && !gameplay){
				if(System.currentTimeMillis() - keyboardCooldown > 1000){
					childList.clear();
					//childList.remove(cube);
					addChild(hero);
					addChild(Factory.newChao());
					gameStarted = true;
					keyboardCooldown = System.currentTimeMillis();
					gameplay = true;
				}
			} else if (gameplay){
				
			} else if (gameOver) {
				if(System.currentTimeMillis() - keyboardCooldown > 1000){
					childList.clear();
					hero = (Tank) Factory.newTankPlayer();
					addChild(hero);
					addChild(Factory.newChao());
					gameStarted = true;
					keyboardCooldown = System.currentTimeMillis();
					gameplay = true;
				}
			}
		}
		
		
		if(gameStarted){
			if (System.currentTimeMillis() - lastCreatedTank > 5000 - score/2) {
				addChild(Factory.newEnemyTank());
				lastCreatedTank = System.currentTimeMillis();
			}
		}
		

		for (int i = 0; i < childList.size(); i++) {
			childList.get(i).Update(diftime);
			if(childList.get(i) instanceof EnemyTank){
				EnemyTank enemy = (EnemyTank) childList.get(i);
				enemy.aim(hero);
				enemy.Shoot(hero);
			}
		}
		
	}

	float soma = 0;
	private float lastScore;

	@Override
	public void render() {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glLoadIdentity();

		soma += 1.0;

		float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
		float[] lightAmbient = { 1.0f, 1.0f, 1.0f, 1.0f };
		float[] lightPosition = { 1.0f, worldX, worldY, worldZ };

		ByteBuffer temp = ByteBuffer.allocateDirect(16);
		temp.order(ByteOrder.nativeOrder());
		glLight(GL_LIGHT0, GL_AMBIENT,
				(FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
		glLight(GL_LIGHT0, GL_DIFFUSE,
				(FloatBuffer) temp.asFloatBuffer().put(lightDiffuse).flip());
		glLight(GL_LIGHT0, GL_POSITION,
				(FloatBuffer) temp.asFloatBuffer().put(lightPosition).flip());

		glEnable(GL_LIGHT0);

		gluLookAt(hero.x, hero.y + 200, hero.z - 10, hero.x, hero.y, hero.z,
				0.0f, 1.0f, 0.0f);

		glPushMatrix();
		{
			glEnable(GL_TEXTURE_2D);
			recursiveDraw(childList, null);
		}
		glPopMatrix();
		if(score != lastScore){
			System.out.println("score " + score);
			lastScore = score;
		}
	}

	private void recursiveDraw(LinkedList<GameObject> childList,
			GameObject parent) {
		for (int i = 0; i < childList.size(); i++) {
			GameObject obj = childList.get(i);

			if (obj instanceof CannonBall) {
				for (int j = 0; j < childList.size(); j++) {
					if (childList.get(j) instanceof EnemyTank) {
						if(((CannonBall) obj).parentName != childList.get(j).parentName)
						if (circleCollision((CannonBall) obj,
								(EnemyTank) childList.get(j))) {
								obj.alive = false;
								childList.get(j).alive = false;
								score += 100;
						}
					}

					if (childList.get(j) instanceof Tank) {
						if(((CannonBall) obj).parentName != childList.get(j).parentName)
						if (circleCollision((CannonBall) obj,
								(Tank) childList.get(j))) {
								obj.alive = false;
								childList.get(j).alive = false;
						}
					}
				}
			}

			if (!obj.alive) {
				childList.remove(obj);
			}

			glPushMatrix();

			if (parent != null) {

				glTranslatef(parent.x + obj.x, parent.y + obj.y, parent.z
						+ obj.z);

				glRotatef(obj.rotateX + parent.rotateX, 1, 0, 0);
				glRotatef(obj.rotateY + parent.rotateY, 0, 1, 0);
				glRotatef(obj.rotateZ + parent.rotateZ, 0, 0, 1);

			} else {

				glTranslatef(obj.x, obj.y, obj.z);

				glRotatef(obj.rotateX, 1, 0, 0);
				glRotatef(obj.rotateY, 0, 1, 0);
				glRotatef(obj.rotateZ, 0, 0, 1);

			}

			glScalef(obj.scaleX, obj.scaleY, obj.scaleZ);
			obj.Render();

			glPopMatrix();
			recursiveDraw(obj.childList, obj);
		}
	}

	private boolean circleCollision(CannonBall obj, EnemyTank enemyTank) {
		float dx = enemyTank.x - obj.x;
		float dy = enemyTank.z - obj.z;
		float radii = obj.collisionR + enemyTank.collisionR;
		if ((dx * dx) + (dy * dy) < radii * radii) {
			return true;
		} else {
			return false;
		}
	}

	private boolean circleCollision(CannonBall obj, Tank tank) {

		float dx = tank.x - obj.x;
		float dy = tank.z - obj.z;
		float radii = obj.collisionR + tank.collisionR;
		if ((dx * dx) + (dy * dy) < radii * radii) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void reshape(int x, int y, int width, int height) {
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		float aspect = (float) width / (float) height;
		gluPerspective((float) FOVY, (float) aspect, (float) NEAR, (float) FAR);
		glMatrixMode(GL_MODELVIEW);
	}
}
